home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / comm / tcp / rxsocket.lha / rxsocket / examples / ping.rexx < prev    next >
Encoding:
OS/2 REXX Batch file  |  1998-10-27  |  4.2 KB  |  182 lines

  1. /*
  2.     This code is NOT from Berkley, but FROM ME :-)
  3.     Very stupid Arexx ping.
  4.     Don't use it to ping localhost or you would ROTFL.
  5.  
  6.     Usage: ping <HOST> [SIZE/N] [NUM/N] [QUICK/S]
  7.  
  8.     HOST     the host name to ping
  9.      SIZE    the size of the imcp echo packet
  10.     NUM        the number of packet to send - 0 means continuos
  11.     QUICK    don't delay, send fast
  12. */
  13.  
  14. if ~show("L","rexxsupport.library") then
  15.     if ~addlib("rexxsupport.library",0,-30) then do
  16.         say "no rexxsupport.library"
  17.         exit
  18.     end
  19. if ~show("L","rxsocket.library") then
  20.     if ~addlib("rxsocket.library",0,-30) then do
  21.         say "no rxsocket.library"
  22.         exit
  23.     end
  24. if ~show("L","rmh.library") then
  25.     if ~addlib("rmh.library",0,-30) then do
  26.         say "no rmh.library"
  27.         exit
  28.     end
  29.  
  30. prg = ProgramName("NOEXT")
  31.  
  32. /** read and parse arguments **/
  33. if ~RMH_ReadArgs("HOST/A,SIZE/K/N,NUM/K/N,QUICK/S") then do
  34.     call PrintFault(IoErr(),prg)
  35.     exit
  36. end
  37.  
  38. addr = resolve(parm.0.value)
  39. if addr=="-1" then call err "no host <"parm.0.value">"
  40.  
  41. host=parm.0.value
  42. if parm.1.flag then
  43.     if parm.1.value>7 & parm.1.value<8000 then dataSize=parm.1.value
  44.     else call err("SIZE must be >7 and <8000")
  45. else dataSize=56
  46.  
  47. if parm.2.flag then
  48.     if parm.2.value>0 then numPkt=parm.2.value
  49.     else call err("NUM must be positive")
  50. else numPkt=1E10
  51.  
  52. wait=~parm.3.flag
  53.  
  54. break=0
  55. signal on BREAK_C
  56.  
  57. /** resolve host name **/
  58. sin.addrAddr=resolve(host)
  59. if sin.addrAddr=="-1" then call err("HOST not found")
  60.  
  61. /** create a RAW ICMP socket **/
  62. sock=socket("INET","RAW","ICMP")
  63. if sock<0 then call err("no socket")
  64.  
  65. /** socket must NOT blocking **/
  66. call IOCtlSocket(sock,"FIONBIO",1)
  67.  
  68. /** we need an ID to recognize our icmp **/
  69. ourID=right(x2c(pragma("ID")),2)
  70. min=1E10
  71. max=0
  72. avg=0
  73. nrec=0
  74. ntrans=0
  75.  
  76. /** create a timer **/
  77. t=CreateTimer()
  78. timSig=TimerSignal(t)
  79.  
  80. if numPkt==1E10 then ps=""
  81. else ps=" Num:" numPkt
  82. say Upper(PRG) host "("sin.addrAddr"):" dataSize "data bytes" ps
  83.  
  84. /** we go:
  85.     wait_for_packet_or_time_to_send
  86.     readpacket if any
  87.     sendpacket if time
  88. **/
  89. call StartTimer(t,wait)
  90. call sendPacket(dataSize)
  91. sel.read.0=sock
  92. go=ntrans<numPkt | numPkt==1
  93. do while go
  94.  
  95.     res=WaitSelect("SEL",,,timSig)
  96.     if res~=0 then call readPacket
  97.  
  98.     if and(sel.signals,timSig)~=0 then do
  99.         call sendPacket(dataSize)
  100.         if wait==0 then call WriteCH("STDOUT",".")
  101.         call StartTimer(t,wait)
  102.     end
  103.     go=ntrans<numPkt
  104. end
  105. signal BREAK_C
  106. exit
  107.  
  108. err:
  109. parse arg msg
  110.     say prg":" msg
  111.     exit
  112.  
  113. pad: PROCEDURE
  114. parse arg string,len
  115.     return copies(d2c(0),len-length(string)) || string
  116.  
  117. d2m: PROCEDURE
  118. parse arg val,len
  119.     return pad(d2c(val),len)
  120.  
  121. sendPacket:
  122. parse arg dataSize
  123.     /** here we create an ICMP echo packet **/
  124.     pktf = ourID || d2m(ntrans,2)
  125.     call GetSysTime("TV")
  126.     pktf=pktf || d2m(tv.secs,4) || d2m(tv.micro,4) || copies("0"x,dataSize-8)
  127.     temp="0800"x || "0000"x || pktf
  128.     pkt="0800"x || d2c(InetCksum(temp)) || pktf
  129.     res=SendTo(sock,pkt,0,"SIN")
  130.     if res~=length(pkt) then do
  131.         e=errno()
  132.         if IsLibOn("TTCP") then es=e
  133.         else es=ErrorString(e)
  134.         call err("send error ("es")")
  135.     end
  136.     ntrans=ntrans+1
  137.     return
  138.  
  139. readPacket:
  140.     /** here we read an ICMP packet and check if it is an ICMP
  141.         echo-replay for us **/
  142.     call GetSysTime("NOW")
  143.     res=RecvFrom(sock,"BUFF",256)
  144.     if res<0 then call err("recv error")
  145.     parse var buff vhl +1 tos +1 len +2 id +2 off +2 ttl +1 rest
  146.     hl=c2d(bitand(vhl,'F'x))*8
  147.     buff=c2x(buff)
  148.     parse var buff +hl type +2 code +2 cksum +4 id +4 seq +4 s +8 m +8 data
  149.     if c2d(len)~=dataSize+8 | type~='00' | code~='00' | id~=c2x(ourID)
  150.         then return
  151.     old.secs=x2d(s)
  152.     old.micro=x2d(m)
  153.     call SubTime("NOW","OLD")
  154.     time=now.secs*1000000+now.micro
  155.     time=time%1000"."time//1000
  156.     time=((time*100)%1)/100
  157.     if wait==1 then
  158.         say c2d(len) "bytes from" sin.AddrAddr": icmp_seq="x2d(seq) "ttl="c2d(ttl) "time="time "ms"
  159.     nrec=nrec+1
  160.     if time>max then max=time
  161.     if time<min then min=time
  162.     avg=avg+time
  163.     return
  164.  
  165. /** statistics **/
  166. BREAK_C:
  167.     if break==1 | sigl<38 then call err("user break")
  168.     if t~="T" then call StopTimer(t)
  169.     break=1
  170.     signal on BREAK_C
  171.     if ntrans>nrec & max>0 then do
  172.         res=WaitSelect("SEL",5)
  173.         if res~=0 then call readPacket
  174.     end
  175.     if ntrans==0 then loss=100
  176.     else loss=(ntrans-nrec)/ntrans*100
  177.     say
  178.     say "---" host "ping statistics ---"
  179.     say ntrans "packets transmitted," nrec "packets received," loss"% packet loss"
  180.     if nrec>0 then say "round-trip min/avg/max =" min"/"|| (((avg/nrec)*100)%1)/100 || "/"max "ms"
  181.     exit
  182.